package org.budo.support.media.encoder.ffmpeg;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.budo.support.assertion.Assert;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.ProcessUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.media.encoder.BudoMediaEncoder;
import org.budo.time.Time;
import org.budo.time.TimePoint;
import org.budo.time.TimeSpan;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Getter
@Setter
@Slf4j
public class BudoFFmpegMediaEncoder implements BudoMediaEncoder {
    private String ffmpegPath;

    @Override
    public void videoCapture(String videoPath, String time, String imagePath) {
        new File(imagePath).getParentFile().mkdirs();

        String ffmpegPath = this.getFfmpegPath();
        Assert.notEmpty(ffmpegPath, "ffmpegPath is empty");

        List<String> commend = new ArrayList<String>();
        commend.add(ffmpegPath);

        commend.add("-y");
        commend.add("-ss");
        commend.add(time);
        commend.add("-i");
        commend.add(videoPath);
        commend.add("-f");
        commend.add("image2");
        commend.add("-t");
        commend.add("0.001");
        commend.add(imagePath);

        InputStream inputStream = ProcessUtil.runCommand(commend);
        String response = IoUtil.toString(inputStream);
        Assert.notEmpty(response, "53 response is empty");

        if (response.contains("Could not open file")) {
            log.error("#55 " + response);
            throw new RuntimeException("#55 ProcessUtil.runCommand error, commend=" + StringUtil.join(commend, " ") + ", response=" + response);
        }
    }

    @Override
    public TimeSpan videoDuration(String videoPath) {
        if (StringUtil.isEmpty(videoPath)) {
            log.error("#60 videoPath=" + videoPath);
            return null;
        }

        String ffmpegPath = this.getFfmpegPath();
        Assert.notEmpty(ffmpegPath, "ffmpegPath is empty");

        List<String> commend = new ArrayList<String>();
        commend.add(ffmpegPath);
        commend.add("-i");
        commend.add(videoPath);

        InputStream inputStream = ProcessUtil.runCommand(commend);
        String response = IoUtil.toString(inputStream);

        int a = response.indexOf("Duration: ");
        if (a < 0) {
            throw new RuntimeException("#65 response=" + response);
        }

        int b = response.indexOf(',', a);
        if (b < 0) {
            throw new RuntimeException("#74 response=" + response);
        }

        if (b - a < 10 + 10) {
            throw new RuntimeException("#74 commend=" + commend + ", response=" + response);
        }

        String durationStr = response.substring(a + 10, b);

        try {
            TimePoint that = Time.when(durationStr, Time.timeFormat("HH:mm:ss.SS"));
            return Time.when(0).datePart().between(that);
        } catch (Exception e) {
            throw new RuntimeException("#98 commend=" + StringUtil.join(commend, " "));
        }
    }
}
